#include "Function.hpp"
#include "EquationSolver.hpp"
#include <iostream>
#include <cmath>

const double Pi = acos(-1.);

class F1 : public Function {
public:
    double operator() (double x) const {
        return sin(x/2)-1;
    }
};

void solve_f1D() {
    std::cout << "Solving sin(x/2) - 1 with x_0=0, x_1=Pi/2" << std::endl;
    Secant_Method solver_f1(F1(), 0, Pi/2);
    double x1 = solver_f1.solve();
    std::cout << "A root is: " << x1 << std::endl;
    std::cout << "Solving sin(x/2) - 1 with x_0=-4*Pi, x_1=-3*Pi" << std::endl;
    Secant_Method solver_f1_(F1(), -4*Pi, -3*Pi);
    double x2 = solver_f1_.solve();
    std::cout << "A root is: " << x2 << std::endl;
}

class F2 : public Function {
public:
    double operator() (double x) const {
        return exp(x)-tan(x);
    }
};

void solve_f2D() {
    std::cout << "Solving exp(x) - tan(x) with x_0=0, x_1=1.4" << std::endl;
    Secant_Method solver_f2(F2(), 0, 1.4);
    double x1 = solver_f2.solve();
    std::cout << "A root is: " << x1 << std::endl;
    std::cout << "Solving exp(x) - tan(x) with x_0=-4.6, x_1=-1.6" << std::endl;
    Secant_Method solver_f2_(F2(), -4.6, -1.6);
    double x2 = solver_f2_.solve();
    std::cout << "A root is: " << x2 << std::endl;
}

class F3 : public Function {
public:
    double operator() (double x) const {
        return pow(x,3)-12*pow(x,2)+3*x+1;
    }
};

void solve_f3D() {
    std::cout << "Solving x^3 - 12x^2 + 3x + 1 with x_0=0, x_1=-0.5" << std::endl;
    Secant_Method solver_f3(F3(), 0, -0.5);
    double x1 = solver_f3.solve();
    std::cout << "A root is: " << x1 << std::endl;
    std::cout << "Solving x^3 - 12x^2 + 3x + 1 with x_0=0, x_1=1" << std::endl;
    Secant_Method solver_f3_(F3(), 0, 1);
    double x2 = solver_f3_.solve();
    std::cout << "A root is: " << x2 << std::endl;
}


int main() {
    std::cout << "Question D:" << std::endl;
    solve_f1D();
    solve_f2D();
    solve_f3D();
    return 0;
}